// ------------------- 调光任务调整 -------------------

// 灯值：允许任意颜色 → 0-100 的亮度
/**
 * @typedef {object} LightValues
 * @property {number} [白光]   0-100
 * @property {number} [蓝光]   0-100
 * @property {number} [红光]   0-100
 * @property {number} [亮度]   0-100
 * 可扩展其它颜色
 */

/**
 * 一个任务（时间段 + 设备 + 亮度）
 * @typedef {object} LightTask
 * @property {[string, string]} timeRange  开始、结束时间，格式 HH:mm:ss
 * @property {string[]}         devices    要控制的设备名称列表
 * @property {LightValues}      values     各颜色亮度
 * @property {number|undefined}      startTS     开始时间，秒
 *  * @property {number|undefined}      endTS     结束时间，秒
 */

/**
 * 灯光组完整结构
 * @typedef {object} LightGroup
 * @property {string}        name      组名称
 * @property {string}        oldName   旧名称（空字符串表示新建）
 * @property {boolean}       enabled   是否启用
 * @property {LightTask[]}   tasks     任务列表
 */

/**
 * PLCTask
 * @typedef {object} PLCTask
 * @property {boolean|number|(boolean|number)[]}    payload  消息负载
 * @property {string|string[]}                  variable  字段名
 */

/**
 * 灯光组数据
 * @type {LightGroup[]} data
 */
const groupData = msg.payload['调光组配置'];

if (!groupData) {
  return;
}

const plcDevice = msg.__plc_device;

/**
 * 把 HH:mm:ss 转成秒
 * @type {(t: string) => number}
 */
const toSec = (t) => t.split(':').reduce((a, b) => a * 60 + +b, 0);

const now = new Date();
const nowTS =
  now.getHours() * 60 * 60 + now.getMinutes() * 60 + now.getSeconds();

function generateTask(data) {
  const allTasks = [];

  // 需要立即触发的任务
  const allTriggerTasks = [];

  // 立马写入PLC的任务
  /** @type {PLCTask[]} */
  const allWritePLCTasks = [];

  // 遍历灯光组
  for (let _idx = 0; _idx < data.length; _idx++) {
    const startTimes = new Set();
    const endTimes = new Set();

    // 任务列表
    const tasks = [];
    let triggerTasks = [];

    const obj = data[_idx];
    const name = obj.name;
    const enabled = !!obj.enabled;

    // 未开启就不创建任务
    if (!enabled) {
      const _plcTask = {
        payload: [],
        variable: [],
      };
      // 获取最后一个任务的设备，并直接把设备关闭
      const lastTask = obj.tasks[obj.tasks.length - 1];
      if (lastTask) {
        const lastDevices = lastTask.devices;
        lastDevices.forEach((dev) => {
          _plcTask.variable.push(dev);
          _plcTask.payload.push(false);
        });
      }
      allWritePLCTasks.push(_plcTask);

      continue;
    }

    // 对着开始时间排序
    obj.tasks.sort((a, b) => {
      a.startTS = toSec(a.timeRange[0]);
      a.endTS = toSec(a.timeRange[1]);

      b.startTS = toSec(b.timeRange[0]);
      b.endTS = toSec(b.timeRange[1]);

      return a.startTS - b.startTS;
    });

    // 遍历灯光组内的任务
    for (let _idx2 = 0; _idx2 < obj.tasks.length; _idx2++) {
      const item = obj.tasks[_idx2];

      // 最后一个任务组
      const isLast = _idx2 === obj.tasks.length - 1;

      const nextItem =
        obj.tasks.length > 1 ? obj.tasks[(_idx2 + 1) % obj.tasks.length] : null;

      const devices = item.devices;
      const values = item.values;

      let [sTime, eTime] = item.timeRange;
      const [nextStartTime, _] = nextItem ? nextItem.timeRange : [];

      // 最后一个就不判断了
      if (!isLast) {
        // 下一个开始时间早于当前的结束时间，那么结束时间就是开始的时间
        if (nextStartTime && nextItem.startTS < item.endTS) {
          eTime = nextStartTime;
        }
      }

      // node.warn({
      //     tasks: obj.tasks,
      //     isLast,
      //     timeRange: item.timeRange,
      //     eTime,
      //     nextStartTime
      // })

      startTimes.add(sTime);
      endTimes.add(eTime);

      const startName = `${name}_${sTime}_开启`;
      const endName = `${name}_${eTime}_关闭`;

      const startTS = item.startTS || toSec(sTime);
      const endTS = toSec(eTime);

      // 时间段属于开启时间范围
      if (nowTS >= startTS && nowTS < endTS) {
        triggerTasks.push(startName);
      }

      const startData = {
        payload: [], // 值
        variable: [], // 字段
        __plc_device: plcDevice,
        _type: 'plc_control',
      };

      const endData = {
        payload: [], // 值
        variable: [], // 字段
        __plc_device: plcDevice,
        _type: 'plc_control',
      };

      devices.forEach((dev) => {
        // 控制代号
        // startData.variable.push(`${dev}_控制代号`);
        // endData.variable.push(`${dev}_控制代号`);

        // startData.payload.push(48);
        // endData.payload.push(48);

        Object.entries(values).forEach(([color, val]) => {
          const key = `${dev}_${color}`;
          // 开启的任务数据
          startData.variable.push(key);
          startData.payload.push(val);
          //关闭的任务数据
          endData.variable.push(key);
          endData.payload.push(0);
        });

        //关闭的的亮度为0
        if (!endData.variable.includes(`${dev}_亮度`)) {
          endData.variable.push(`${dev}_亮度`);
          endData.payload.push(0);
        }

        // 开灯动作
        startData.variable.push(dev);
        startData.payload.push(true);

        // 关灯动作
        endData.variable.push(dev);
        endData.payload.push(false);
      });

      // 设置开启任务
      tasks.push({
        name: startName,
        time: sTime,
        ts: startTS,
        payload: startData,
        type: 'start',
      });

      // 设置关闭任务
      tasks.push({
        name: endName,
        time: eTime,
        ts: endTS,
        payload: endData,
        type: 'end',
      });
    }

    // 时间段之外的时间就是都是关闭
    if (tasks.length > 1) {
      if (tasks[0].ts > nowTS || nowTS > tasks[tasks.length - 1].ts) {
        triggerTasks = [tasks[tasks.length - 1].name];
      }
    }

    allTasks.push(
      ...tasks.filter((item, index) => {
        if (item.type !== 'end') return true;
        // 保留最后一个
        if (tasks.length - 1 === index) true;
        // 当结束任务和下一个开始时间重叠，就没有结束任务
        if (!startTimes.has(item.time)) return true;
        return false;
      })
    );
    allTriggerTasks.push(...triggerTasks);
  }

  return {
    allTasks,
    allTriggerTasks,
    allWritePLCTasks,
  };
}

// 生成灯光组任务
const { allTasks, allTriggerTasks, allWritePLCTasks } = generateTask(groupData);

// node.warn({
//     allTriggerTasks,
//     nowTS
// })

// 返回数据
return [
  {
    payload: allTasks,
    triggerTasks: allTriggerTasks,
    __plc_device: msg.__plc_device,
  },
  {
    payload: allWritePLCTasks.length > 0 ? allWritePLCTasks : undefined,
    __plc_device: msg.__plc_device,
  },
];

// ------------------- 调光任务调整 -------------------
